using Godot;
using System;
using System.Collections.Generic;
using System.Net;

public class BlockWorld : Node2D
{
    public List<LargeChunk> chunks = new List<LargeChunk>();

    public LargeChunk ActiveChunk;
    public Vector2I Postion = new Vector2I(0, 0);

    public static int Tick = 20;
    public static String WorldName = "overworld";
    public static int Seed = 0;
    public TileMap Tilemap_Font, TileMap_Back;
    public static Player player;
    public Thread ChunkThread = new Thread();
    public Mutex ChunkThreadMutex = new Mutex();
    bool ThreadState = true;

    public float tps = 0;
    private int tps_ = 0;
    public override void _Ready()
    {
        _ = Materials.Air;


        player = GetNode<Player>("Player");
        Tilemap_Font = GetNode<TileMap>("Tilemap_Font");
        TileMap_Back = GetNode<TileMap>("Tilemap_Back");
        ActiveChunk = new LargeChunk(this, 0, 0);

        if (ActiveChunk.Load())
        {

        }
        else
        {
            ActiveChunk.Spawn();
            ActiveChunk.Save();
            int y = -ActiveChunk.GetHight(LargeChunk.ChunkSize / 2, 0) * 16;
            player.Position = new Vector2(LargeChunk.ChunkSize / 2 * 16, y);
        }


        Tilemap_Font.TileSet = BlockTileSet.tileSet;
        TileMap_Back.TileSet = BlockTileSet.tileSet;
        UpdataTileMap();
        var thread = new System.Threading.Thread(ChunkUpdate);
        thread.Start();

        var tps_thread = new System.Threading.Thread(() =>
        {
            while (true)
            {
                System.Threading.Thread.Sleep(1000);
                tps = tps_;
                tps_ = 0;
            }
        });
        tps_thread.Start();
    }
    public override void _ExitTree() => ActiveChunk.Save();

    public async void ChunkUpdate()
    {
        while (true)
        {
            System.Threading.Thread.Sleep(1000 / Tick);
            for (int i = 0; i < ActiveChunk.Updatelist.Count; i++)
            {
                var pos = ActiveChunk.Updatelist[i];
                UpdataBlock(pos);
            }
            ActiveChunk.Updatelist.Clear();
            ActiveChunk.TickV2();
            tps_ += 1;
            if (!GetThreadState())
            {
                break;
            }
        }
    }
    public void UpdataTileMap()
    {
        for (int z = 0; z < 2; z++)
        {
            for (int x = 0; x < LargeChunk.ChunkSize; x++)
            {
                for (int y = 0; y < LargeChunk.ChunkSize; y++)
                {
                    UpdataBlock(new Vector3I(x, y, z));
                }
            }
        }
    }
    public void UpdataBlock(Vector3I v3)
    {
        BlockData block = ActiveChunk.GetBlock(v3);
        int id = block.GetTileId();
        if (v3.Z == 0) Tilemap_Font.SetCell(v3.X, -v3.Y, id);
        if (v3.Z == 1) TileMap_Back.SetCell(v3.X, -v3.Y, id);
    }
    public BlockData GetBlock(int x, int y, int z) => ActiveChunk.GetBlock(x, y, z);
    public BlockData GetBlock(Vector3I v3) => ActiveChunk.GetBlock(v3);
    public BlockData SetBlock(int x, int y, int z, BlockMaterial material) => ActiveChunk.SetBlock(new Vector3I(x, y, z), material);
    public BlockData SetBlock(Vector3I v3, BlockMaterial material) => ActiveChunk.SetBlock(v3, material);


    private bool GetThreadState()
    {
        return ThreadState;
    }
}
